home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 351-375 / disk_368 / popmenu / popmenu_pak.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  18KB  |  745 lines

  1. /***************************************************************************
  2.  * popmenu_pak.c -general-purpose dynamic Pop-up Menu routines to help make*
  3.  *                programming alot easier.                                 *
  4.  *                (c) 1990 VIDEOWORKS Computer Applications                *
  5.  *                All rights reserved.                                     *
  6.  *                129 Orchard Avenue, Rocky Mount, VA 24151                *
  7.  *                (703) 483-8219 / 489-3863                                *
  8.  *                                                                         *
  9.  *                Designed and Developed by Paul T. Miller                 *
  10.  *                                                                         *
  11.  * Program Name:  N/A                                                      *
  12.  * Version:       1                                                        *
  13.  * Revision:      0                                                        *
  14.  *-------------------------------------------------------------------------*
  15.  * File: (popmenu_pak.c) dynamic window-relative pop-up menu routines      *
  16.  *-------------------------------------------------------------------------*
  17.  * Modification History                                                    *
  18.  * Date     Author   Comment                                               *
  19.  * -------- ------   -------                                               *
  20.  * 03-29-90    PTM   Created. Initialization/Setup
  21.  * 04-01-90    PTM   PMenu drawing/handling. RastPort FONT characteristics
  22.  * 05-07-90    PTM   Modify PMenu box expansion to fit in window
  23.  * 05-09-90    PTM   Move itemtext positioning to drawmenu()
  24.  *
  25.  ***************************************************************************/
  26.  
  27. #include "popmenu_pak.h"
  28.  
  29. #ifndef GRAPHICS_GFXMACROS_H
  30. #include <graphics/gfxmacros.h>
  31. #endif
  32.  
  33. /* Here are some constants for itemtext placement and item sizes */
  34. #define PMENU_WOFF      16    /* sixteen pixels wider than longest text */
  35. #define PITEM_VOFF      2     /* extra pixels for item (+font height) */
  36. #define PITEM_YOFF      2     /* vertical index into item for text */
  37. #define PITEM_XOFF      2     /* horizontal index into item for text */
  38.  
  39. struct PMenu *BuildPMenu(item, flags, inum, title, id)
  40. struct PMenuItem *item;
  41. USHORT flags;
  42. SHORT inum;
  43. UBYTE *title;
  44. USHORT id;
  45. {
  46.    struct PMenu *pmenu;
  47.    struct IntuiText *itext = NULL;
  48.    struct Border *border;
  49.    struct Gadget *gad;
  50.  
  51.    /* Allocate memory for menu, gadget, gadget text, and border */
  52.  
  53.    pmenu = (struct PMenu *)AllocMem(sizeof(struct PMenu), MEMF_CLEAR);
  54.    if (!pmenu) return(NULL);
  55.  
  56.    gad = (struct Gadget *)AllocMem(sizeof(struct Gadget), MEMF_CLEAR);
  57.    if (!gad)
  58.    {
  59.       FreeMem(pmenu, sizeof(struct PMenu));
  60.       return(NULL);
  61.    }
  62.  
  63.    border = (struct Border *)AllocMem(sizeof(struct Border), MEMF_CLEAR);
  64.    if (!border)
  65.    {
  66.       FreeMem(gad, sizeof(struct Gadget));
  67.       FreeMem(pmenu, sizeof(struct PMenu));
  68.       return(NULL);
  69.    }
  70.  
  71.    itext = (struct IntuiText *)AllocMem(sizeof(struct IntuiText), MEMF_CLEAR);
  72.    if (!itext)
  73.    {
  74.       FreeMem(border, sizeof(struct Border));
  75.       FreeMem(gad, sizeof(struct Gadget));
  76.       FreeMem(pmenu, sizeof(struct PMenu));
  77.       return(NULL);
  78.    }
  79.  
  80.    if (flags & SHADOWED)
  81.       border->Count = 8;
  82.    else
  83.       border->Count = 5;
  84.  
  85.    border->XY = (SHORT *)AllocMem(sizeof(SHORT)*16, MEMF_CLEAR);
  86.    border->FrontPen = 1;
  87.    border->BackPen = 0;
  88.    border->DrawMode = JAM1;
  89.  
  90.    pmenu->FirstPItem = item;
  91.    pmenu->Flags = flags;
  92.    pmenu->MenuName = (UBYTE *)AllocMem(80, MEMF_CLEAR);
  93.    if (title)
  94.    {
  95.       strcpy(pmenu->MenuName, title);
  96.       pmenu->Flags |= TITLED;    /* title supplied by user */
  97.    }
  98.  
  99.    if (pmenu->FirstPItem)
  100.    {
  101.       if (inum < 1) inum = 1;
  102.       pmenu->ActiveItem = GetPItem(pmenu, inum);
  103.       pmenu->Flags |= PREDEFINED;
  104.    }
  105.    itext->FrontPen = 1;    /* Build text for user-controlled menu title */
  106.    itext->BackPen = 0;
  107.    itext->DrawMode = JAM1;
  108.    itext->IText = pmenu->MenuName;
  109.  
  110.    gad->NextGadget = NULL;
  111.    gad->GadgetType = BOOLGADGET;
  112.    gad->Activation = GADGIMMEDIATE | FOLLOWMOUSE;
  113.    gad->Flags = GADGHCOMP;
  114.    gad->GadgetRender = (APTR)border;
  115.    gad->SelectRender = NULL;
  116.    gad->MutualExclude = NULL;
  117.    gad->SpecialInfo = NULL;
  118.    gad->GadgetText = itext;
  119.    gad->GadgetID = id;
  120.    gad->UserData = (APTR)pmenu;
  121.    pmenu->PMenuGadget = gad;
  122.  
  123.    return(pmenu);
  124. }
  125.  
  126. void SetPMenuColor(pmenu, frontpen, backpen)
  127. struct PMenu *pmenu;
  128. USHORT frontpen, backpen;
  129. {
  130.    struct Border *border;
  131.    struct IntuiText *itext;
  132.  
  133.    if (pmenu)
  134.    {
  135.       itext = (struct IntuiText *)pmenu->PMenuGadget->GadgetText;
  136.       border = (struct Border *)pmenu->PMenuGadget->GadgetRender;
  137.       if (itext)
  138.       {
  139.          itext->FrontPen = frontpen;
  140.          itext->BackPen = backpen;
  141.       }
  142.       if (border)
  143.       {
  144.          border->FrontPen = frontpen;
  145.          border->BackPen = backpen;
  146.       }
  147.    }
  148. }
  149.  
  150. InitPMenu(window, pmenu, x, y)
  151. struct Window *window;
  152. struct PMenu *pmenu;
  153. SHORT x, y;
  154. {
  155.    struct RastPort *rp = window->RPort;
  156.    struct Gadget *gad;
  157.    ULONG flags;
  158.  
  159.    if (!window || !pmenu)
  160.       return(NULL);
  161.  
  162.    flags = window->IDCMPFlags;
  163.    ModifyIDCMP(window, flags | GADGETUP);
  164.  
  165.    pmenu->PMenuWindow = window;
  166.  
  167.    /* no user-set width, so find width/height of activation box */
  168.    if (pmenu->Width == 0)
  169.       pmenu->Width = (SHORT)find_maxpitemwidth(pmenu) + PMENU_WOFF;
  170.  
  171.    if (pmenu->Height == 0)
  172.       pmenu->Height = rp->TxHeight+PITEM_VOFF;
  173.  
  174.    /* find out where in the window to render the window */
  175.    if (x == -1)
  176.       pmenu->LeftEdge = window->Width - pmenu->Width - 5;
  177.    else if (x < -1)
  178.       pmenu->LeftEdge = window->Width + x;
  179.    else
  180.       pmenu->LeftEdge = x;
  181.  
  182.    if (y == -1)
  183.       pmenu->TopEdge = window->Height - pmenu->Height - 5;
  184.    else if (y < -1)
  185.       pmenu->TopEdge = window->Height + y;
  186.    else
  187.       pmenu->TopEdge = y;
  188.  
  189.    /* set up activation gadget attributes */
  190.    gad = pmenu->PMenuGadget;
  191.    gad->LeftEdge = pmenu->LeftEdge;
  192.    gad->TopEdge = pmenu->TopEdge;
  193.    gad->Width = pmenu->Width;
  194.    gad->Height = pmenu->Height;
  195.  
  196.    calc_border(pmenu);
  197.  
  198.    pmenu->Flags |= MENUENABLED;
  199.    pmenu->Flags |= MENU_INIT;
  200.  
  201.    AddGadget(window, pmenu->PMenuGadget, -1);
  202.    RefreshPMenu(pmenu);
  203.  
  204.    return(1);
  205. }
  206.  
  207. find_maxpitemwidth(pmenu)
  208. struct PMenu *pmenu;
  209. {
  210.    int length, max = 0;
  211.    struct PMenuItem *item;
  212.  
  213.    for (item = pmenu->FirstPItem; item; item = item->NextPItem)
  214.    {
  215.       if (item->Flags & ITEMTEXT)
  216.       {
  217.          length = IntuiTextLength((struct IntuiText *)item->ItemFill);
  218.          if (length > max) max = length;
  219.       }
  220.    }
  221.    return(max);
  222. }
  223.  
  224. void calc_border(pmenu)
  225. struct PMenu *pmenu;
  226. {
  227.    struct Border *b;
  228.    SHORT *dat;
  229.  
  230.    if (pmenu)
  231.    {
  232.       b = (struct Border *)pmenu->PMenuGadget->GadgetRender;
  233.       dat = b->XY;
  234.  
  235.       if (pmenu->Flags & SHADOWED)
  236.       {
  237.          b->Count = 8;
  238.          dat[0] = dat[2] = pmenu->Width+1;
  239.          dat[1] = dat[4] = 1;
  240.          dat[3] = dat[5] = pmenu->Height+1;
  241.          dat[6] = dat[11] = dat[12] = dat[13] = dat[14] = 0;
  242.          dat[7] = dat[9] = dat[15] = pmenu->Height;
  243.          dat[8] = dat[10] = pmenu->Width;
  244.       }
  245.       else
  246.       {
  247.          b->Count = 5;
  248.          dat[0] = dat[1] = dat[3] = dat[6] = dat[8] = dat[9] = 0;
  249.          dat[2] = dat[4] = pmenu->Width;
  250.          dat[5] = dat[7] = pmenu->Height;
  251.       }
  252.    }
  253. }
  254.  
  255. void RefreshPMenu(pmenu)
  256. struct PMenu *pmenu;
  257. {
  258.    struct IntuiText *itext;
  259.    struct PMenuItem *item;
  260.    int x, y, w, h;
  261.    UBYTE bpen;
  262.  
  263.    bpen = pmenu->PMenuGadget->GadgetText->BackPen;
  264.  
  265.    if (pmenu && (pmenu->Flags & MENU_INIT))
  266.    {
  267.       if (pmenu->Flags & TITLED)
  268.          pmenu->PMenuGadget->GadgetText->IText = pmenu->MenuName;
  269.       else
  270.       {
  271.          item = pmenu->ActiveItem;
  272.          if (item->Flags & ITEMTEXT)
  273.          {
  274.             itext = (struct IntuiText *)pmenu->ActiveItem->ItemFill;
  275.             pmenu->PMenuGadget->GadgetText->IText = itext->IText;
  276.          }
  277.       }
  278.       itext = pmenu->PMenuGadget->GadgetText;
  279.       itext->LeftEdge = (pmenu->Width - IntuiTextLength(itext))/2;
  280.       itext->TopEdge = PITEM_YOFF;
  281.       x = pmenu->LeftEdge;
  282.       y = pmenu->TopEdge;
  283.       w = pmenu->Width;
  284.       h = pmenu->Height;
  285.       SetDrMd(pmenu->PMenuWindow->RPort, JAM1);
  286.       SetAPen(pmenu->PMenuWindow->RPort, bpen);
  287.       RectFill(pmenu->PMenuWindow->RPort, x, y, x+w, y+h);
  288.       RefreshGList(pmenu->PMenuGadget, pmenu->PMenuWindow, NULL, 1);
  289.    }
  290. }
  291.  
  292. void RemovePMenu(pmenu)
  293. struct PMenu *pmenu;
  294. {
  295.    if (pmenu && pmenu->Flags & MENU_INIT)
  296.    {
  297.       pmenu->Flags &= ~MENU_INIT;
  298.       pmenu->Flags &= ~MENUENABLED;
  299.       RemoveGadget(pmenu->PMenuWindow, pmenu->PMenuGadget);
  300.    }
  301. }
  302.  
  303. void FreePMenu(pmenu)
  304. struct PMenu *pmenu;
  305. {
  306.    struct Border *border;
  307.  
  308.    if (pmenu)
  309.    {
  310.       RemovePMenu(pmenu);
  311.  
  312.       FreeMem(pmenu->PMenuGadget->GadgetText, sizeof(struct IntuiText));
  313.       FreeMem(pmenu->MenuName, 80);
  314.  
  315.       border = (struct Border *)pmenu->PMenuGadget->GadgetRender;
  316.       if (border)
  317.       {
  318.          FreeMem(border->XY, sizeof(SHORT) * 16);
  319.          FreeMem(border, sizeof(struct Border));
  320.       }
  321.       FreeMem(pmenu->PMenuGadget, sizeof(struct Gadget));
  322.       FreeMem(pmenu, sizeof(struct PMenu));
  323.    }
  324. }
  325.  
  326. void SetActiveItem(pmenu, inum)
  327. struct PMenu *pmenu;
  328. SHORT inum;
  329. {
  330.    struct PMenuItem *item;
  331.  
  332.    if (inum < 1) return;
  333.  
  334.    if (pmenu && (pmenu->Flags & COMMPMENU))
  335.    {
  336.       item = GetPItem(pmenu, inum);
  337.       if (item)
  338.       {
  339.          pmenu->ActiveItem = item;
  340.          RefreshPMenu(pmenu);
  341.       }
  342.    }
  343. }
  344.  
  345. struct PMenuItem *GetPItem(pmenu, inum)
  346. struct PMenu *pmenu;
  347. SHORT inum;
  348. {
  349.    struct PMenuItem *item;
  350.    UCOUNT i = 1;
  351.  
  352.    for (item = pmenu->FirstPItem; item; item = item->NextPItem, i++)
  353.       if (i == inum)
  354.          return(item);
  355.  
  356.    return(NULL);
  357. }
  358.  
  359. SHORT GetPItemNum(pmenu, item)
  360. struct PMenu *pmenu;
  361. struct PMenuItem *item;
  362. {
  363.    struct PMenuItem *pitem;
  364.    SHORT i = 0;
  365.  
  366.    if (item == NULL) return(0);
  367.  
  368.    if (pmenu->FirstPItem == item)
  369.       return(1);
  370.  
  371.    for (pitem = pmenu->FirstPItem; pitem; pitem = pitem->NextPItem, i++)
  372.       if (pitem == item)
  373.          return((SHORT)(i+1));
  374.  
  375.    return(0);
  376. }
  377.  
  378. CountPMenuItems(pmenu)
  379. struct PMenu *pmenu;
  380. {
  381.    struct PMenuItem *item;
  382.    UCOUNT i;
  383.  
  384.    if (pmenu->FirstPItem == NULL)
  385.       return(0);
  386.  
  387.    for (i = 0, item = pmenu->FirstPItem; item; item = item->NextPItem, i++)
  388.       ;
  389.  
  390.    return(i+1);
  391. }
  392.  
  393. /* Sets the menu activation box of a popup menu to specified text:
  394.    Only if an initial constant title was supplied with BuildPMenu() */
  395.  
  396. void SetPMenuText(pmenu, text)
  397. struct PMenu *pmenu;
  398. UBYTE *text;
  399. {
  400.    if (pmenu)
  401.       if (pmenu->Flags & TITLED)
  402.       {
  403.          strcpy(pmenu->MenuName, text);
  404.          RefreshPMenu(pmenu);
  405.       }
  406. }
  407.  
  408. USHORT HandlePMenu(pmenu)
  409. struct PMenu *pmenu;
  410. {
  411.    ULONG oldflags;
  412.    struct Window *win;
  413.    struct BitMap *sbm;
  414.    struct PMenuItem *item;
  415.    struct IntuiMessage *message;
  416.    ULONG class;
  417.    USHORT code, inum;
  418.    SHORT mx, my;
  419.    SHORT lnum = 0, mousemoved = 0;
  420.  
  421.    if (!pmenu) return(NULL);
  422.  
  423.    calc_menusize(pmenu);
  424.    sbm = savebackground(pmenu);
  425.  
  426.    drawpmenu(pmenu);
  427.  
  428.    win = pmenu->PMenuWindow;
  429.    oldflags = win->IDCMPFlags;
  430.    ReportMouse(win, TRUE);
  431.    ModifyIDCMP(win, oldflags | MOUSEMOVE | MOUSEBUTTONS);
  432.  
  433.    lnum = GetPItemNum(pmenu, pmenu->ActiveItem);
  434.    complement_item(pmenu, lnum);
  435.  
  436.    while (1)
  437.    {
  438.       WaitPort(win->UserPort);
  439.       while (message = (struct IntuiMessage *)GetMsg(win->UserPort))
  440.       {
  441.          class = message->Class;
  442.          code = message->Code;
  443.          mx = message->MouseX;
  444.          my = message->MouseY;
  445.  
  446.          ReplyMsg(message);
  447.  
  448.          switch (class)
  449.          {
  450.             case MOUSEMOVE:
  451.                mousemoved = 1;
  452.                break;
  453.             case MOUSEBUTTONS:
  454.                switch (code)
  455.                {
  456.                   case SELECTUP:
  457.                      item = getmenuitem(pmenu, mx, my);
  458.                      restorebackground(pmenu, sbm);
  459.                      ModifyIDCMP(win, oldflags);
  460.                      inum = GetPItemNum(pmenu, item);
  461.                      if (!(pmenu->Flags & TITLED))
  462.                         SetActiveItem(pmenu, inum);
  463.                      return(inum);
  464.                      break;
  465.                }
  466.                break;
  467.          }
  468.       }
  469.       if (mousemoved)
  470.       {
  471.          mousemoved = 0;
  472.          handle_items(pmenu, mx, my, &lnum);
  473.       }
  474.    }
  475. }
  476.  
  477. struct PMenuItem *getmenuitem(pmenu, mx, my)
  478. struct PMenu *pmenu;
  479. SHORT mx, my;
  480. {
  481.    struct PMenuItem *item;
  482.    SHORT x, y, x2, y2;
  483.    USHORT num;
  484.  
  485.    if (!pmenu) return(NULL);
  486.  
  487.    x = pmenu->JazzX;
  488.    y = pmenu->JazzY;
  489.    x2 = pmenu->JazzX + pmenu->BeatX;
  490.    y2 = pmenu->JazzY + pmenu->BeatY;
  491.  
  492.    if (mx > x && my > y && mx < x2 && my < y2)
  493.    {
  494.       num = (my - y - PITEM_YOFF) / pmenu->Height;
  495.       item = GetPItem(pmenu, (SHORT)(num+1));
  496.       if (item->Flags & ITEMENABLED)
  497.          return(item);
  498.    }
  499.    return(NULL);
  500. }
  501.  
  502. void calc_menusize(pmenu)
  503. struct PMenu *pmenu;
  504. {
  505.    UCOUNT num;
  506.  
  507.    num = CountPMenuItems(pmenu);
  508.  
  509.    if (pmenu->Flags & TITLED)    /* titled, so find width of largest item */
  510.       pmenu->BeatX = find_maxpitemwidth(pmenu) + PMENU_WOFF;
  511.    else
  512.       pmenu->BeatX = pmenu->Width;  /* otherwise width/height of menu box */
  513.  
  514.    pmenu->BeatY = pmenu->Height * (num-1) + PITEM_VOFF-1;
  515.    if (pmenu->Flags & SHADOWED)
  516.    {
  517.       pmenu->BeatX++;
  518.       pmenu->BeatY++;
  519.    }
  520.    pmenu->JazzX = pmenu->LeftEdge;     /* upper-left corner of expanded */
  521.    pmenu->JazzY = pmenu->TopEdge;
  522.  
  523.    /* shift menu into window if it extends out right side */
  524.    if (pmenu->JazzX + pmenu->BeatX > pmenu->PMenuWindow->Width)
  525.       pmenu->JazzX = pmenu->LeftEdge + pmenu->Width - pmenu->BeatX + 1;
  526.  
  527.    if (pmenu->Flags & COMMPMENU)
  528.    {
  529.       num = GetPItemNum(pmenu, pmenu->ActiveItem);
  530.       pmenu->JazzY -= ((num-1) * pmenu->Height);
  531.       while (pmenu->JazzY <= 0)
  532.          pmenu->JazzY += pmenu->Height;
  533.    }
  534. }
  535.  
  536. struct BitMap *savebackground(pmenu)
  537. struct PMenu *pmenu;
  538. {
  539.    int x, y, w, h;
  540.    struct Window *win;
  541.    struct BitMap *bm;
  542.  
  543.    win = pmenu->PMenuWindow;
  544.    x = win->LeftEdge + pmenu->JazzX;
  545.    y = win->TopEdge + pmenu->JazzY;
  546.    w = pmenu->BeatX + 1;
  547.    h = pmenu->BeatY + 1;
  548.  
  549.    bm = allocbitmap((USHORT)w, (USHORT)h, (UBYTE)win->RPort->BitMap->Depth);
  550.    if (bm)
  551.       BltBitMap(win->RPort->BitMap, x, y, bm, 0, 0, w, h, 0xc0, 0xff, NULL);
  552.  
  553.    return(bm);
  554. }
  555.  
  556. void restorebackground(pmenu, bm)
  557. struct PMenu *pmenu;
  558. struct BitMap *bm;
  559. {
  560.    int x, y, w, h;
  561.    struct Window *win;
  562.  
  563.    if (!pmenu) return;
  564.  
  565.    win = pmenu->PMenuWindow;
  566.    x = win->LeftEdge + pmenu->JazzX;
  567.    y = win->TopEdge + pmenu->JazzY;
  568.    w = pmenu->BeatX + 1;
  569.    h = pmenu->BeatY + 1;
  570.  
  571.    if (bm)
  572.    {
  573.       BltBitMap(bm, 0, 0, win->RPort->BitMap, x, y, w, h, 0xc0, 0xff, NULL);
  574.       freebitmap(bm);
  575.    }
  576.    pmenu->Flags &= ~MIDRAWN;
  577. }
  578.  
  579. void drawpmenu(pmenu)
  580. struct PMenu *pmenu;
  581. {
  582.    int x, y, w, h, i;
  583.    struct RastPort *rp;
  584.    struct PMenuItem *item;
  585.    struct IntuiText *itext;
  586.    UBYTE fpen, bpen;
  587.  
  588.    rp = pmenu->PMenuWindow->RPort;
  589.  
  590.    SetDrMd(rp, JAM1);
  591.  
  592.    fpen = pmenu->PMenuGadget->GadgetText->FrontPen;
  593.    bpen = pmenu->PMenuGadget->GadgetText->BackPen;
  594.  
  595.    x = pmenu->JazzX;
  596.    y = pmenu->JazzY;
  597.    w = pmenu->BeatX;
  598.    h = pmenu->BeatY;
  599.  
  600.    if (pmenu->Flags & SHADOWED)
  601.    {
  602.       w--;
  603.       h--;
  604.    }
  605.  
  606.    /* draw the menu outline */
  607.    SetAPen(rp, fpen);
  608.    RectFill(rp, x, y, x+w, y+h);
  609.    SetAPen(rp, bpen);
  610.    RectFill(rp, x+1, y+1, x+w-2, y+h-2);
  611.  
  612.    SetAPen(rp, fpen);
  613.    if (pmenu->Flags & SHADOWED)
  614.    {
  615.       Move(rp, x+w+1, y+1);
  616.       Draw(rp, x+w+1, y+h+1);
  617.       Draw(rp, x+1, y+h+1);
  618.    }
  619.  
  620.    for (i = 0, item = pmenu->FirstPItem; item; item = item->NextPItem, i++)
  621.    {
  622.       if (item->Flags & ITEMTEXT)
  623.       {
  624.          itext = (struct IntuiText *)item->ItemFill;
  625.          itext->TopEdge = PITEM_YOFF;
  626.  
  627.          /* position item text */
  628.          if (item->Flags & CENTERED)
  629.             itext->LeftEdge = (w - IntuiTextLength(itext))/2;
  630.          else
  631.             itext->LeftEdge = PITEM_XOFF;
  632.  
  633.          SetAPen(rp, itext->FrontPen);
  634.          Move(rp, x+itext->LeftEdge,
  635.                   y + itext->TopEdge + (i * pmenu->Height) + rp->TxBaseline);
  636.          Text(rp, itext->IText, strlen(itext->IText));
  637.       }
  638.    }
  639.    pmenu->Flags |= MIDRAWN;
  640. }
  641.  
  642. void handle_items(pmenu, mx, my, lnum)
  643. struct PMenu *pmenu;
  644. SHORT mx, my, *lnum;
  645. {
  646.    SHORT x, y, x2, y2;
  647.    USHORT num;
  648.  
  649.    if (!pmenu) return;
  650.  
  651.    x = pmenu->JazzX;
  652.    y = pmenu->JazzY;
  653.    x2 = pmenu->JazzX + pmenu->BeatX - 1;
  654.    y2 = pmenu->JazzY + pmenu->BeatY - 1;
  655.    if (pmenu->Flags & SHADOWED)
  656.    {
  657.       x2--;
  658.       y2--;
  659.    }
  660.  
  661.    if (mx > x && my > y && mx < x2 && my < y2)
  662.    {
  663.       num = ((my - y - PITEM_VOFF) / pmenu->Height) + 1;
  664.       if (num != *lnum)
  665.       {
  666.          if (*lnum != 0)
  667.             complement_item(pmenu, *lnum);
  668.  
  669.          complement_item(pmenu, num);
  670.       }
  671.       *lnum = num;
  672.       return;
  673.    }
  674.    if (*lnum != 0)
  675.       complement_item(pmenu, *lnum);
  676.    *lnum = 0;
  677. }
  678.  
  679. void complement_item(pmenu, num)
  680. struct PMenu *pmenu;
  681. SHORT num;
  682. {
  683.    int x, y, w, h;
  684.    struct PMenuItem *item;
  685.    struct RastPort *rp = pmenu->PMenuWindow->RPort;
  686.    BYTE old_mode = rp->DrawMode;
  687.  
  688.    item = GetPItem(pmenu, num);
  689.  
  690.    if (pmenu == NULL || item == NULL)
  691.       return;
  692.  
  693.    if (item->Flags & ITEMENABLED)
  694.    {
  695.       x = pmenu->JazzX+1;
  696.       y = pmenu->JazzY + (num-1)*pmenu->Height+1;
  697.       w = pmenu->BeatX-4;
  698.       h = pmenu->Height-1;
  699.  
  700.       SetDrMd(rp, COMPLEMENT);
  701.       SetAPen(rp, 1);
  702.       RectFill(rp, x, y, x+w, y+h);
  703.       SetDrMd(rp, old_mode);
  704.    }
  705. }
  706.  
  707. struct BitMap *allocbitmap(width, height, depth)
  708. USHORT width, height;
  709. UBYTE depth;
  710. {
  711.    struct BitMap *bm;
  712.    register int i;
  713.  
  714.    bm = (struct BitMap *)AllocMem(sizeof(struct BitMap), MEMF_CLEAR);
  715.    if (bm)
  716.    {
  717.       InitBitMap(bm, (long)depth, (long)width, (long)height);
  718.  
  719.       for (i = 0; i < depth; i++)
  720.       {
  721.          bm->Planes[i] = (PLANEPTR)AllocRaster(width, height);
  722.          if (!bm->Planes[i])
  723.          {
  724.             freebitmap(bm);
  725.             return(NULL);
  726.          }
  727.       }
  728.    }
  729.    return(bm);
  730. }
  731.  
  732. void freebitmap(bm)
  733. struct BitMap *bm;
  734. {
  735.    register int i;
  736.  
  737.    if (bm)
  738.    {
  739.       for (i = 0; i < bm->Depth; i++)
  740.          if (bm->Planes[i])
  741.             FreeMem(bm->Planes[i], (long)(bm->BytesPerRow * bm->Rows));
  742.       FreeMem(bm, sizeof(struct BitMap));
  743.    }
  744. }
  745.